import java.util.Random;
import java.util.Scanner;

public class Minesweeper {
    private int rows;
    private int cols;
    private int mines;
    private char[][] board;          // 显示给玩家的面板
    private char[][] mineField;      // 存储实际地雷位置的面板
    private boolean[][] revealed;    // 记录哪些格子已被揭开
    private boolean[][] flagged;     // 记录哪些格子被标记
    private boolean gameOver;
    private boolean gameWon;
    private int cellsRevealed;

    public Minesweeper() {
        this(9, 9, 10); // 默认 9x9 的面板，10个地雷
    }

    public Minesweeper(int rows, int cols, int mines) {
        this.rows = rows;
        this.cols = cols;
        this.mines = mines;
        this.board = new char[rows][cols];
        this.mineField = new char[rows][cols];
        this.revealed = new boolean[rows][cols];
        this.flagged = new boolean[rows][cols];
        this.gameOver = false;
        this.gameWon = false;
        this.cellsRevealed = 0;
        
        initializeBoard();
        placeMines();
        calculateNumbers();
    }

    // 初始化面板
    private void initializeBoard() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                board[i][j] = '.';
                mineField[i][j] = '0';
                revealed[i][j] = false;
                flagged[i][j] = false;
            }
        }
    }

    // 随机放置地雷
    private void placeMines() {
        Random random = new Random();
        int minesPlaced = 0;
        
        while (minesPlaced < mines) {
            int row = random.nextInt(rows);
            int col = random.nextInt(cols);
            
            if (mineField[row][col] != '*') {
                mineField[row][col] = '*';
                minesPlaced++;
            }
        }
    }

    // 计算每个非地雷格子周围的地雷数量
    private void calculateNumbers() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (mineField[i][j] != '*') {
                    int count = countAdjacentMines(i, j);
                    mineField[i][j] = (char) (count + '0');
                }
            }
        }
    }

    // 计算指定位置周围的地雷数量
    private int countAdjacentMines(int row, int col) {
        int count = 0;
        
        for (int i = -1; i <= 1; i++) {
            for (int j = -1; j <= 1; j++) {
                if (i == 0 && j == 0) continue;
                
                int newRow = row + i;
                int newCol = col + j;
                
                if (isValidPosition(newRow, newCol) && mineField[newRow][newCol] == '*') {
                    count++;
                }
            }
        }
        
        return count;
    }

    // 检查位置是否有效
    private boolean isValidPosition(int row, int col) {
        return row >= 0 && row < rows && col >= 0 && col < cols;
    }

    // 显示面板
    public void displayBoard() {
        System.out.println();
        System.out.print("  ");
        for (int j = 0; j < cols; j++) {
            System.out.print(j + " ");
        }
        System.out.println();
        
        for (int i = 0; i < rows; i++) {
            System.out.print(i + " ");
            for (int j = 0; j < cols; j++) {
                if (flagged[i][j]) {
                    System.out.print("F ");
                } else if (revealed[i][j]) {
                    if (mineField[i][j] == '0') {
                        System.out.print("  ");
                    } else {
                        System.out.print(mineField[i][j] + " ");
                    }
                } else {
                    System.out.print(". ");
                }
            }
            System.out.println();
        }
        System.out.println();
    }

    // 揭开一个格子
    public void revealCell(int row, int col) {
        if (!isValidPosition(row, col) || revealed[row][col] || flagged[row][col]) {
            return;
        }
        
        // 如果揭开的是地雷，游戏结束
        if (mineField[row][col] == '*') {
            revealed[row][col] = true;
            gameOver = true;
            revealAllMines();
            return;
        }
        
        // 揭开格子
        revealed[row][col] = true;
        cellsRevealed++;
        
        // 如果揭开的格子周围没有地雷，自动揭开周围的格子
        if (mineField[row][col] == '0') {
            for (int i = -1; i <= 1; i++) {
                for (int j = -1; j <= 1; j++) {
                    revealCell(row + i, col + j);
                }
            }
        }
        
        // 检查是否获胜
        checkWin();
    }

    // 标记或取消标记一个格子
    public void toggleFlag(int row, int col) {
        if (!isValidPosition(row, col) || revealed[row][col]) {
            return;
        }
        
        flagged[row][col] = !flagged[row][col];
    }

    // 揭开所有地雷（游戏结束时调用）
    private void revealAllMines() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (mineField[i][j] == '*') {
                    revealed[i][j] = true;
                }
            }
        }
    }

    // 检查是否获胜
    private void checkWin() {
        int totalCells = rows * cols;
        if (cellsRevealed == totalCells - mines) {
            gameWon = true;
            gameOver = true;
        }
    }

    // 游戏主循环
    public void playGame() {
        Scanner scanner = new Scanner(System.in);
        
        System.out.println("欢迎来到扫雷游戏!");
        System.out.println("命令说明:");
        System.out.println("  r <行> <列> - 揭开格子");
        System.out.println("  f <行> <列> - 标记/取消标记地雷");
        System.out.println("  q - 退出游戏");
        System.out.println();
        
        while (!gameOver) {
            displayBoard();
            System.out.print("请输入命令: ");
            String input = scanner.nextLine().trim();
            
            if (input.isEmpty()) {
                continue;
            }
            
            String[] parts = input.split(" ");
            String command = parts[0].toLowerCase();
            
            if (command.equals("q")) {
                System.out.println("游戏退出。");
                break;
            }
            
            if (parts.length < 3) {
                System.out.println("无效命令！请使用格式: <命令> <行> <列>");
                continue;
            }
            
            try {
                int row = Integer.parseInt(parts[1]);
                int col = Integer.parseInt(parts[2]);
                
                if (!isValidPosition(row, col)) {
                    System.out.println("坐标超出范围！请输入有效的坐标。");
                    continue;
                }
                
                if (command.equals("r")) {
                    revealCell(row, col);
                } else if (command.equals("f")) {
                    toggleFlag(row, col);
                } else {
                    System.out.println("无效命令！使用 r 揭开格子，f 标记地雷，q 退出游戏。");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入有效的数字坐标！");
            }
        }
        
        // 游戏结束，显示最终面板
        displayBoard();
        
        if (gameWon) {
            System.out.println("恭喜你！你赢了！");
        } else if (gameOver) {
            System.out.println("游戏结束！你踩到地雷了。");
        }
        
        scanner.close();
    }

    public static void main(String[] args) {
        // 创建并开始游戏
        Minesweeper game = new Minesweeper();
        game.playGame();
    }
}
